#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import asyncio
import aiohttp
from typing import Optional, Callable
from ..core.logger import Logger
import logging

class Downloader:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Referer': 'https://www.bilibili.com'
        }
    
    async def download_file(self, url: str, save_path: str, headers: Optional[dict] = None,
                          progress_callback: Optional[Callable[[int, int], None]] = None) -> None:
        """下载文件
        
        Args:
            url: 下载地址
            save_path: 保存路径
            headers: 请求头
            progress_callback: 进度回调函数，参数为(已下载大小, 总大小)
        """
        if headers is None:
            headers = {}
        
        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers) as response:
                response.raise_for_status()
                total_size = int(response.headers.get('content-length', 0))
                downloaded_size = 0
                
                # 确保目录存在
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                
                with open(save_path, 'wb') as f:
                    async for chunk in response.content.iter_chunked(8192):
                        if chunk:
                            f.write(chunk)
                            downloaded_size += len(chunk)
                            if progress_callback:
                                progress_callback(downloaded_size, total_size)
    
    async def download_video(self, url: str, output_path: str, 
                           progress_callback: Optional[Callable[[int, int], None]] = None):
        """下载视频或音频"""
        try:
            self.logger.info(f"开始下载: {url}")
            self.logger.info(f"输出路径: {output_path}")
            
            # 确保输出目录存在
            output_dir = os.path.dirname(output_path)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url, headers=self.headers) as response:
                    if response.status not in [200, 206]:
                        error_msg = await response.text()
                        self.logger.error(f"下载失败: {response.status} - {error_msg}")
                        raise ValueError(f"下载失败: {response.status} - {error_msg}")
                    
                    total_size = int(response.headers.get('content-length', 0))
                    self.logger.info(f"文件总大小: {total_size} 字节")
                    
                    downloaded_size = 0
                    with open(output_path, 'wb') as f:
                        async for chunk in response.content.iter_chunked(8192):
                            if chunk:
                                f.write(chunk)
                                downloaded_size += len(chunk)
                                if progress_callback:
                                    progress_callback(downloaded_size, total_size)
                    
                    self.logger.info(f"下载完成: {output_path}")
                    return True
        except Exception as e:
            self.logger.error(f"下载异常: {str(e)}")
            # 如果下载失败，删除可能存在的部分文件
            if os.path.exists(output_path):
                try:
                    os.remove(output_path)
                except:
                    pass
            raise
    
    async def download_danmaku(self, url: str, output_path: str):
        """下载弹幕"""
        try:
            self.logger.info(f"开始下载弹幕: {url}")
            self.logger.info(f"输出路径: {output_path}")
            
            # 确保输出目录存在
            output_dir = os.path.dirname(output_path)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url, headers=self.headers) as response:
                    if response.status != 200:
                        error_msg = await response.text()
                        self.logger.error(f"下载弹幕失败: {response.status} - {error_msg}")
                        raise ValueError(f"下载失败: {response.status} - {error_msg}")
                    
                    content = await response.read()
                    with open(output_path, 'wb') as f:
                        f.write(content)
                    
                    self.logger.info(f"弹幕下载完成: {output_path}")
                    return True
        except Exception as e:
            self.logger.error(f"下载弹幕异常: {str(e)}")
            # 如果下载失败，删除可能存在的部分文件
            if os.path.exists(output_path):
                try:
                    os.remove(output_path)
                except:
                    pass
            raise
    
    async def download_subtitle(self, url: str, output_path: str):
        """下载字幕"""
        try:
            self.logger.info(f"开始下载字幕: {url}")
            self.logger.info(f"输出路径: {output_path}")
            
            # 确保输出目录存在
            output_dir = os.path.dirname(output_path)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url, headers=self.headers) as response:
                    if response.status != 200:
                        error_msg = await response.text()
                        self.logger.error(f"下载字幕失败: {response.status} - {error_msg}")
                        raise ValueError(f"下载失败: {response.status} - {error_msg}")
                    
                    content = await response.read()
                    with open(output_path, 'wb') as f:
                        f.write(content)
                    
                    self.logger.info(f"字幕下载完成: {output_path}")
                    return True
        except Exception as e:
            self.logger.error(f"下载字幕异常: {str(e)}")
            # 如果下载失败，删除可能存在的部分文件
            if os.path.exists(output_path):
                try:
                    os.remove(output_path)
                except:
                    pass
            raise 